import Layout from '../../components/docs-layout';
import toast from 'react-hot-toast';

export const meta = {
  title: 'useToaster() API',
};

export default ({ children }) => <Layout meta={meta}>{children}</Layout>;

# `useToaster()` API

The `useToaster()` hook provides a **headless toast management system** for building custom notification UIs. It manages toast state and lifecycle without rendering any components.

It handles pausing on hover, auto-removal, and provides a 1-second removal delay with `visible` flag for smooth animations.

**Alternative**: Use [`useToasterStore()`](/docs/use-toaster-store) if you already have a toaster instance and only need the state.

### Importing

```jsx
import { useToaster } from 'react-hot-toast';
```

You can also import from the headless entry point to exclude UI components:

```jsx
import { useToaster } from 'react-hot-toast/headless';
```

**Note**: [React Hot Toast 2.0](/docs/version-2) includes **custom render functions** for easier custom components.

## API Reference

### Parameters

```tsx
useToaster(
  toastOptions?: DefaultToastOptions,
  toasterId?: string
)
```

| Parameter      | Type                  | Default     | Description                                     |
| -------------- | --------------------- | ----------- | ----------------------------------------------- |
| `toastOptions` | `DefaultToastOptions` | `undefined` | Default options for all toasts in this instance |
| `toasterId`    | `string`              | `'default'` | Unique identifier for this toaster instance     |

### Returns

```tsx
{
  toasts: Toast[];
  handlers: {
    startPause: () => void;
    endPause: () => void;
    updateHeight: (toastId: string, height: number) => void;
    calculateOffset: (toast: Toast, options?: OffsetOptions) => number;
  };
}
```

#### `toasts`

Array of all toasts in this toaster instance, including hidden ones for animation purposes.

#### `handlers`

- **`startPause()`**: Pause all toast timers (useful for hover states)
- **`endPause()`**: Resume all toast timers
- **`updateHeight(toastId, height)`**: Update toast height for offset calculations
- **`calculateOffset(toast, options)`**: Calculate vertical offset for toast positioning

## Multiple Toasters

You can create multiple independent toaster instances by providing a unique `toasterId`. See the [Multiple Toasters](/docs/multi-toaster) guide for detailed examples.

```jsx
const sidebar = useToaster({ duration: 5000 }, 'sidebar');
toast('Sidebar notification', { toasterId: 'sidebar' });
```

## Examples

### Basic Implementation

```jsx
import toast, { useToaster } from 'react-hot-toast/headless';

const Notifications = () => {
  const { toasts, handlers } = useToaster();
  const { startPause, endPause } = handlers;

  return (
    <div onMouseEnter={startPause} onMouseLeave={endPause}>
      {toasts
        .filter((toast) => toast.visible)
        .map((toast) => (
          <div key={toast.id} {...toast.ariaProps}>
            {toast.message}
          </div>
        ))}
    </div>
  );
};

// Create toasts from anywhere
toast('Hello World');
```

### Animated Implementation

This example uses all `toasts` (including hidden ones) to enable smooth animations. The `toast.visible` property controls opacity, while the 1-second removal delay provides time for exit animations.

**Live Demo**: [CodeSandbox](https://codesandbox.io/s/react-hot-toast-usetoaster-headless-example-zw7op?file=/src/App.js)

```jsx
import { useToaster } from 'react-hot-toast/headless';

const AnimatedNotifications = () => {
  const { toasts, handlers } = useToaster();
  const { startPause, endPause, calculateOffset, updateHeight } = handlers;

  return (
    <div
      style={{
        position: 'fixed',
        top: 8,
        left: 8,
      }}
      onMouseEnter={startPause}
      onMouseLeave={endPause}
    >
      {toasts.map((toast) => {
        const offset = calculateOffset(toast, {
          reverseOrder: false,
          gutter: 8,
        });

        const ref = (el) => {
          if (el && typeof toast.height !== 'number') {
            const height = el.getBoundingClientRect().height;
            updateHeight(toast.id, height);
          }
        };

        return (
          <div
            key={toast.id}
            ref={ref}
            style={{
              position: 'absolute',
              width: '200px',
              background: 'papayawhip',
              transition: 'all 0.5s ease-out',
              opacity: toast.visible ? 1 : 0,
              transform: `translateY(${offset}px)`,
            }}
            {...toast.ariaProps}
          >
            {toast.message}
          </div>
        );
      })}
    </div>
  );
};
```


## Usage with React Native

The headless API works perfectly with React Native. View the [React Native example](<https://snack.expo.io/@timo/react-hot-toast---usetoaster()---react-native>) for implementation details.
